package com.campus.counseling.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.counseling.entity.SysUser;
import com.campus.counseling.entity.TestRecord;
import com.campus.counseling.entity.TestResult;
import com.campus.counseling.model.common.exception.ServiceException;
import com.campus.counseling.model.dto.TestResultDTO;
import com.campus.counseling.model.mapper.TestRecordMapper;
import com.campus.counseling.model.mapper.TestResultMapper;
import com.campus.counseling.model.query.TestResultQuery;
import com.campus.counseling.model.vo.TestResultVO;
import com.campus.counseling.service.TestResultService;
import com.campus.counseling.service.SysUserService;
import com.campus.counseling.util.SecurityUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class TestResultServiceImpl extends ServiceImpl<TestResultMapper, TestResult> implements TestResultService {

    private final ObjectMapper objectMapper;
    private final SysUserService userService;
    private final TestRecordMapper testRecordMapper;

    @Override
    public TestResult getByRecordId(Long recordId) {
        return baseMapper.selectOne(new LambdaQueryWrapper<TestResult>()
            .eq(TestResult::getRecordId, recordId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitTestResult(TestResultDTO resultDTO) {
        // 先检查是否已存在结果
        TestResult existingResult = getOne(new LambdaQueryWrapper<TestResult>()
            .eq(TestResult::getRecordId, resultDTO.getRecordId()));
        
        // 如果已存在结果，执行更新
        if (existingResult != null) {
            TestResult updateResult = new TestResult();
            BeanUtils.copyProperties(resultDTO, updateResult);
            updateResult.setId(existingResult.getId());
            updateResult.setUpdateTime(LocalDateTime.now());
            
            if (!updateById(updateResult)) {
                throw new ServiceException("更新测试结果失败");
            }
            return;
        }
        
        // 不存在则创建新记录
        TestResult result = new TestResult();
        BeanUtils.copyProperties(resultDTO, result);
        result.setCreateTime(LocalDateTime.now());
        result.setUpdateTime(LocalDateTime.now());
        
        if (!save(result)) {
            throw new ServiceException("保存测试结果失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void review(Long id, Long reviewerId, String comments) {
        TestResult result = getById(id);
        if (result == null) {
            throw new RuntimeException("测试结果不存在");
        }

        result.setReviewedBy(reviewerId);
        result.setReviewComments(comments);
        result.setReviewTime(LocalDateTime.now());
        
        updateById(result);
    }

    @Override
    public Map<String, Double> parseDimensionScores(String dimensionScores) {
        try {
            if (dimensionScores == null || dimensionScores.isEmpty()) {
                return new HashMap<>();
            }
            return objectMapper.readValue(dimensionScores, new TypeReference<Map<String, Double>>() {});
        } catch (Exception e) {
            log.error("解析维度得分失败", e);
            return new HashMap<>();
        }
    }

    @Override
    public String formatDimensionScores(Map<String, Double> dimensionScores) {
        try {
            return objectMapper.writeValueAsString(dimensionScores);
        } catch (Exception e) {
            log.error("格式化维度得分失败", e);
            return "{}";
        }
    }

    @Override
    public Page<TestResultVO> getResultPage(TestResultQuery query) {
        // 获取当前用户信息
        Long currentUserId = SecurityUtils.getUserId();
        String userRole = SecurityUtils.getLoginUser().getRole();
        
        // 创建测试记录的查询条件
        LambdaQueryWrapper<TestRecord> recordWrapper = new LambdaQueryWrapper<>();
        
        // 根据角色设置查询权限
        if ("admin".equals(userRole) || "superadmin".equals(userRole)) {
            // 管理员可以查看所有记录
        } else if ("counselor".equals(userRole)) {
            // 咨询师可以查看所有学生的记录
        } else {
            // 学生只能查看自己的记录
            recordWrapper.eq(TestRecord::getUserId, currentUserId);
        }
        
        // 如果有用户名搜索条件，先通过用户服务查找对应的用户ID
        if (StringUtils.hasText(query.getUsername())) {
            List<Long> userIds = userService.getUserIdsByUsername(query.getUsername());
            if (!userIds.isEmpty()) {
                recordWrapper.in(TestRecord::getUserId, userIds);
            } else {
                // 如果没有找到匹配的用户，返回空结果
                return new Page<>();
            }
        }
        
        // 获取符合条件的测试记录ID列表
        List<Long> recordIds = testRecordMapper.selectList(recordWrapper)
            .stream()
            .map(TestRecord::getId)
            .collect(Collectors.toList());
        
        // 创建测试结果的分页查询
        Page<TestResult> page = new Page<>(query.getPageNum(), query.getPageSize());
        LambdaQueryWrapper<TestResult> wrapper = new LambdaQueryWrapper<>();
        
        // 如果有记录ID列表，添加到查询条件
        if (!recordIds.isEmpty()) {
            wrapper.in(TestResult::getRecordId, recordIds);
        } else {
            // 如果没有符合条件的记录，返回空结果
            return new Page<>();
        }
        
        // 如果有评估等级条件，添加到查询条件
        if (StringUtils.hasText(query.getLevel())) {
            wrapper.eq(TestResult::getLevel, query.getLevel());
        }
        
        // 按创建时间倒序排序
        wrapper.orderByDesc(TestResult::getCreateTime);
        
        page = page(page, wrapper);
        
        List<TestResultVO> records = page.getRecords().stream()
            .map(result -> {
                TestResultVO vo = new TestResultVO();
                BeanUtils.copyProperties(result, vo);
                
                // 获取测试记录信息
                TestRecord record = testRecordMapper.selectById(result.getRecordId());
                if (record != null) {
                    vo.setTestId(record.getTestId());
                    vo.setUserId(record.getUserId());
                    
                    // 设置开始和结束时间，并计算测试用时
                    LocalDateTime startTime = record.getStartTime();
                    LocalDateTime endTime = record.getEndTime();
                    vo.setStartTime(startTime);
                    vo.setEndTime(endTime);
                    
                    // 计算测试用时（秒）
                    if (startTime != null && endTime != null) {
                        Duration duration = Duration.between(startTime, endTime);
                        vo.setTestDuration(duration.getSeconds());
                    }
                    
                    vo.setStatus(record.getStatus());
                    
                    // 获取测试标题
                    if (record.getTestId() != null) {
                        vo.setTestTitle(testRecordMapper.getTestTitleById(record.getTestId()));
                    }
                    
                    // 获取用户信息
                    if (record.getUserId() != null) {
                        SysUser user = userService.getById(record.getUserId());
                        if (user != null) {
                            vo.setUsername(user.getUsername());
                            log.info("Setting username: {} for user ID: {}", user.getUsername(), record.getUserId());
                        }
                    }
                }
                
                // 如果有评审人，获取评审人姓名
                if (result.getReviewedBy() != null) {
                    vo.setReviewerName(userService.getRealName(result.getReviewedBy()));
                }
                
                return vo;
            })
            .collect(Collectors.toList());
        
        // 创建返回的分页对象
        Page<TestResultVO> voPage = new Page<>();
        BeanUtils.copyProperties(page, voPage, "records");
        voPage.setRecords(records);
        
        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveResult(TestResult result) {
        // 先检查是否已存在结果
        TestResult existingResult = getOne(new LambdaQueryWrapper<TestResult>()
            .eq(TestResult::getRecordId, result.getRecordId()));
        
        // 如果已存在结果，执行更新
        if (existingResult != null) {
            result.setId(existingResult.getId());
            result.setUpdateTime(LocalDateTime.now());
            updateById(result);
            return;
        }

        // 确保必要字段不为空
        if (result.getTotalScore() == null) {
            result.setTotalScore(0);
        }
        if (result.getDimensionScores() == null) {
            result.setDimensionScores("{}");
        }
        if (result.getLevel() == null) {
            result.setLevel("");
        }
        if (result.getAnalysis() == null) {
            result.setAnalysis("");
        }
        if (result.getSuggestions() == null) {
            result.setSuggestions("");
        }
        if (result.getReviewComments() == null) {
            result.setReviewComments("");
        }
        if (result.getCreateTime() == null) {
            result.setCreateTime(LocalDateTime.now());
        }
        if (result.getUpdateTime() == null) {
            result.setUpdateTime(LocalDateTime.now());
        }
        
        // 使用 baseMapper 直接插入
        baseMapper.insert(result);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateResult(TestResult result) {
        result.setUpdateTime(LocalDateTime.now());
        updateById(result);
    }
} 